"""
生命游戏
"""

import json
import pygame
import sys
from random import randint

from block import Block
from setting import Setting


def lifeinit(setting):
    for row in range(setting.areanum+2):
        for col in range(setting.areanum+2):
            setting.lifestat.append(0)
    setting.backstat = setting.lifestat[:]
    for row in range(1, setting.areanum+1):
        for col in range(1, setting.areanum+1):
            setting.blocks.append(Block(setting, row, col))
    liferandom(setting)


def liferandom(setting):
    for row in range(setting.areanum+2):
        for col in range(setting.areanum+2):
            if row == 0 or row > setting.areanum or col == 0 or col > setting.areanum:
                live = 0
            else:
                live = randint(0, 20) // 18
            setting.lifestat[row * (setting.areanum+2)+col] = live
    blocksetall(setting)
    setting.age = 1
    setting.count = 1


def blockset(setting, row, col):
    live = setting.lifestat[(row + 1) * (setting.areanum + 2) + col + 1]
    setting.blocks[row  * setting.areanum + col].set_live(live)


def blocksetall(setting):
    for row in range(setting.areanum):
        for col in range(setting.areanum):
            blockset(setting, row, col)

def lifeset(setting, row, col, live):
    setting.lifestat[(row + 1) * (setting.areanum + 2) + col + 1] = live
    blockset(setting, row, col)

def lifechange(setting):
    back = setting.lifestat[:]
    for row in range(1, setting.areanum+1):
        for col in range(1, setting.areanum+1):
            result = (back[(row-1) * (setting.areanum + 2) + col - 1]
                      + back[(row - 1) * (setting.areanum + 2) + col]
                      + back[(row - 1) * (setting.areanum + 2) + col + 1]
                      + back[row * (setting.areanum + 2) + col - 1]
                      + back[row * (setting.areanum + 2) + col + 1]
                      + back[(row + 1) * (setting.areanum + 2) + col - 1]
                      + back[(row + 1) * (setting.areanum + 2) + col]
                      + back[(row + 1) * (setting.areanum + 2) + col + 1])
            if result == 3:
                setting.lifestat[row * (setting.areanum + 2) + col] = 1
            elif result == 2:
                pass
            else:
                setting.lifestat[row * (setting.areanum + 2) + col] = 0
    if sum(setting.lifestat) == sum(back):
        same = True
        for i in range(len(back)):
            if back[i]!=setting.lifestat[i]:
                same = False
                break
        if same:
            savedata(setting)
            liferandom(setting)
    if sum(setting.lifestat) == sum(setting.backstat):
        same = True
        for i in range(len(setting.backstat)):
            if setting.backstat[i]!=setting.lifestat[i]:
                same = False
                break
        if same:
            savedata(setting)
            liferandom(setting)
    setting.backstat = back[:]

    blocksetall(setting)
    return sum(setting.lifestat)

def savedata(setting):
    filename = setting.filename + str(setting.fileno)+".json"
    setting.fileno += 1
    with open(filename, 'w') as f:
        json.dump(setting.lifestat, f)
    liferandom(setting)


def loaddata(setting):
    with open(setting.filename, 'r') as f:
        setting.lifestat = json.load(f)

def eventprocess(event, setting):
    if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE:
            pygame.quit()
            sys.exit()
        elif event.key == pygame.K_s:
            savedata(setting)
        elif event.key == pygame.K_l:
            loaddata(setting)
        elif event.key == pygame.K_0:
            liferandom(setting)
        elif event.key == pygame.K_UP:
            if setting.speed > 5:
                setting.speed -= 5
        elif event.key == pygame.K_DOWN:
            setting.speed += 5

    if event.type == pygame.MOUSEBUTTONDOWN:
        if pygame.mouse.get_pressed()[0]:  # 左键
            pos = pygame.mouse.get_pos()
            row = pos[1] // (setting.areasize[1] + 1)
            col = pos[0] // (setting.areasize[0] + 1)
            if row >= 1 and row <= setting.areanum and col >= 0 and col <= setting.areanum:
                lifeset(setting, row - 1, col - 1, 1)


def run():
    pygame.init()
    screen_size = (610, 680)
    screen = pygame.display.set_mode(screen_size)
    pygame.display.set_caption("life game")
    setting = Setting(screen)
    lifeinit(setting)

    fpsClock = pygame.time.Clock()
    setting.count = 1
    setting.age = 1

    while True:
        for event in pygame.event.get():
            eventprocess(event, setting)

        screen.fill((230, 230, 230))
        for block in setting.blocks:
            block.update()

        title = setting.font.render("第{:d}代生命，生命个数:{:d}，速度:{:d}".format(setting.age, sum(setting.lifestat), setting.fps*100//setting.speed),
                                    True, (0, 0, 0), (255, 255, 255))
        screen.blit(title, (10, 620))

        pygame.display.flip()

        if setting.count % setting.speed == 0:
            setting.age += 1
            if lifechange(setting) == 0:
                sys.exit()

        setting.count += 1
        fpsClock.tick(setting.fps)


run()


